package com.liber.sun.utils;

import com.liber.sun.support.MyResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * Created by sunlingzhi on 2017/12/21.
 */
public class MyHttpUtils {

    public static String GET(String urlString, String encode, Map<String, String> headers, String... m) throws IOException, URISyntaxException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        //若地址中设计到了特殊字符，就不能使用String代替URI来访问。必须用%0xxx的方式来代替特殊字符
        //但这种方式不直观，所有先将string转为URL，在通过URL生成URI。
        URL url=new URL(urlString);
        URI uri=new URI(url.getProtocol(), url.getHost()+":"+url.getPort(), url.getPath(), url.getQuery(),null);

        HttpGet httpGet = new HttpGet(uri);
        //设置header
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpGet.setHeader(entry.getKey(), entry.getValue());
            }
        }
        CloseableHttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();



        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entity, encode);
        }
        EntityUtils.consume(entity);

        //释放链接
        response.close();
        client.close();

        return body;

    }

    public static String POST(String url, String encode, Map<String, String> headers, Map<String, String> params,
                              List<MultipartFile> multipartFiles, String... m) throws IOException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        //创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);
        //设置header
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.setHeader(entry.getKey(),entry.getValue());
            }
        }
        //构建body
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        //文件数据
        if (multipartFiles != null&& multipartFiles.size() > 0) {
            for(MultipartFile multipartFile:multipartFiles){
                builder.addBinaryBody("file", multipartFile.getInputStream(), ContentType.MULTIPART_FORM_DATA, multipartFile.getOriginalFilename());
            }
        }
        //parameter
        ContentType contentType = ContentType.create("text/plain", Charset.forName(encode));//解决中文乱码
        if (params != null&& params.size() > 0) {
            for (Map.Entry<String, String> key : params.entrySet()) {
                builder.addTextBody(key.getKey(), key.getValue(),contentType);
            }
        }

        HttpEntity entityIn = builder.build();
        //设置参数到请求对象中
        httpPost.setEntity(entityIn);


        //执行请求操作，并拿到结果（同步阻塞）
        CloseableHttpResponse response = client.execute(httpPost);
        HttpEntity entityOut = response.getEntity();
        if (entityOut != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entityOut, encode);
        }
        EntityUtils.consume(entityOut);
        //释放链接
        response.close();
        client.close();
        return body;
    }

    public static String POSTRawString(String url, String encode,Map<String, String> headers, String stringJson,  String... m) throws IOException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        HttpPost httpost = new HttpPost(url);
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpost.setHeader(entry.getKey(), entry.getValue());
            }
        }

        StringEntity stringEntity = new StringEntity(stringJson, encode);

        httpost.setEntity(stringEntity);


        CloseableHttpResponse httpResponse = client.execute(httpost);
        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entity, encode);
        }
        EntityUtils.consume(entity);
        //释放链接
        httpResponse.close();
        client.close();
        return body;

    }

    public static String DELETE(String url,String encode,Map<String,String> headers,String ... m) throws IOException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        HttpDelete httpdelete = new HttpDelete(url);
        //设置header
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpdelete.setHeader(entry.getKey(), entry.getValue());
            }
        }

        CloseableHttpResponse response = client.execute(httpdelete);
        HttpEntity entity = response.getEntity();

        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entity, encode);
        }
        EntityUtils.consume(entity);

        //释放链接
        response.close();
        client.close();

        return body;

    }

    public static String PUTRawString(String url, String encode,Map<String, String> headers, String stringJson,  String... m) throws IOException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        HttpPut httpput = new HttpPut(url);
        httpput.setHeader("Content-type", "application/json");
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpput.setHeader(entry.getKey(), entry.getValue());
            }
        }

        StringEntity stringEntity = new StringEntity(stringJson, encode);
        httpput.setEntity(stringEntity);


        CloseableHttpResponse httpResponse = client.execute(httpput);
        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entity, encode);
        }
        EntityUtils.consume(entity);
        //释放链接
        httpResponse.close();
        client.close();
        return body;

    }

    public static String PUTRawFile(String url, String encode, Map<String, String> headers, File file, String... m) throws IOException {
        String body = "";
        CloseableHttpClient client = checkAuth(m);
        if (client == null) {
            return "验证输入参数存在问题";
        }
        HttpPut httpput = new HttpPut(url);
        if (headers != null && headers.size() > 0) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpput.setHeader(entry.getKey(), entry.getValue());
            }
        }


        FileEntity fileEntity=new FileEntity(file);
        httpput.setEntity(fileEntity);


        CloseableHttpResponse httpResponse = client.execute(httpput);
        HttpEntity entity = httpResponse.getEntity();

        if (entity != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entity, encode);
        }
        EntityUtils.consume(entity);
        //释放链接
        httpResponse.close();
        client.close();
        return body;

    }

    public static CloseableHttpClient checkAuth(String... m) {
        if (m.length == 2) {//需要验证
            CredentialsProvider credsProvider = new BasicCredentialsProvider();
            UsernamePasswordCredentials creds = new UsernamePasswordCredentials(m[0], m[1]);
            AuthScope scope = new AuthScope(AuthScope.ANY);
            credsProvider.setCredentials(scope, creds);
            return HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
        } else if (m.length == 0) {//不用验证
            return HttpClients.createDefault();
        } else {
            return null;
        }
    }





    /**
     *
     * @param url
     * @param encode
     * @param paramTag   服务容器接受的参数是Tag
     * @return
     * @throws IOException
     */
    public static String POSTFileToModelContainer(String url, String encode, String paramTag,File file) throws IOException {
        String body = "";
        CloseableHttpClient client =HttpClients.createDefault();
        //创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);
        //设置header
        httpPost.setHeader("Connection", "Keep-Alive");
        httpPost.setHeader("Account-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
        //构建body
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();

        builder.addBinaryBody("myfile", MyFileUtils.getFileContentByInputStream(file), ContentType.MULTIPART_FORM_DATA, file.getName());

        //parameter
        ContentType contentType = ContentType.create("text/plain", Charset.forName(encode));//解决中文乱码
        builder.addTextBody("tag", paramTag,contentType);


        HttpEntity entityIn = builder.build();
        //设置参数到请求对象中
        httpPost.setEntity(entityIn);


        //执行请求操作，并拿到结果（同步阻塞）
        CloseableHttpResponse response = client.execute(httpPost);
        HttpEntity entityOut = response.getEntity();
        if (entityOut != null) {
            //按指定编码转换结果实体为String类型
            body = EntityUtils.toString(entityOut, encode);
        }
        EntityUtils.consume(entityOut);
        //释放链接
        response.close();
        client.close();
        return body;
    }


    public static MyResponse getMyResponse(String urlString) throws IOException {
        URL url=new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打开连接
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(30000);
        connection.setReadTimeout(30000);

        return new MyResponse(connection.getContentLength(),
                connection.getContentType(),
                connection.getHeaderField("Content-Disposition"),
                connection.getInputStream()
        );
    }

    /**
     * 将response的InputStream写到指定basicPath路径中去
     *
     * @param basicPath 存储的目录

     * @return 返回Reponse中的文件名
     * @throws IOException
     */
    public static String getMyFile(String basicPath, String urlString) throws IOException {
        URL url=new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();// 打开连接
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(30000);
        connection.setReadTimeout(30000);

        //attachment; filename=fileName
        String Content = connection.getHeaderField("Content-Disposition");
        String filename = Content.substring(StringUtils.lastIndexOf(Content, "=") + 1);
        MyFileUtils.writeInputStreamToFile(connection.getInputStream(), new File(basicPath + filename));
        return filename;
    }
}
